from pyodbc import Connection, Cursor
import pyodbc as po

class ODBC(object):
    """
    ODBC 数据库基类.
    """

    def __init__(this, DriverName, EngineName, **kwargs):
        """
        ###########################################
        [功能描述] 初始化数据库连接.
        [参数列表] 1. DriverName    驱动名;
                   2. EngineName    引擎名;
                   3. **kwargs      动态连接参数.
        [返回类型] 无.
        ###########################################
        """
        try:
            print('使用驱动 {%s} 连接到 %s%s' % (DriverName, EngineName, '...'))
            this._ODBC__conDatabase = Connection
            this._ODBC__conDatabase = po.connect(**kwargs)
            this._ODBC__curDatabase = Cursor
            this._ODBC__curDatabase = this._ODBC__conDatabase.cursor()
        except po.Error as poErr:
            print(poErr.args[1])
            print('无法连接到 %s!' % EngineName)

    @property
    def Cursor(this):
        """
        ##################
        属性: 游标 (只读).
        ##################
        """
        return this._ODBC__curDatabase

    @property
    def InstalledDrivers(this):
        """
        ##########################
        属性: 已安装的驱动 (只读).
        ##########################
        """
        return po.drivers()

    def SelectDriver(this, Name):
        """
        ########################################
        [功能描述] 从过滤后的名称列表中选择驱动.
        [参数列表] Name 名称.
        [返回类型] str.
        ########################################
        """
        lstDrivers = [d for d in this.InstalledDrivers if Name.lower() in d.lower()]
        intCount = len(lstDrivers)
        if intCount > 0:
            if intCount == 1:
                return lstDrivers[0]
            print('|---可用驱动列表')
            for intIdx, strDriver in enumerate(lstDrivers):
                print('   |---[%d]. %s' % (intIdx + 1, strDriver))

            while True:
                strIdx = input('\x08请输入要使用的驱动索引号 (回车使用第一个): ')
                if strIdx == '':
                    return lstDrivers[0]
                if strIdx.isdigit():
                    try:
                        intIdx = int(strIdx) - 1
                        return lstDrivers[intIdx]
                    except IndexError:
                        print('索引超出范围')

                    intIdx = int(strIdx)
                else:
                    print('输入错误')

        else:
            print('找不到 %s 驱动')

    def Execute(this, Sql, NeedCommit = False, Params = None):
        """
        ###########################################################
        [功能描述] 执行 SQL 语句.
        [参数列表] 1. Sql           SQL 语句;
                   2. NeedCommit    是否需要提交 (可选/默认不提交).
                   3. Params        参数 (可选/默认参数为空);
        [返回类型] 无.
        -----------------------------------------------------------
        NeedCommit 用于 INSERT/UPDATE/DELETE 语句.
        ###########################################################
        
        1. Sql: SQL 语句
        2. Params: 参数
        3. NeedCommit: 是否需要提交 
        """
        try:
            if Params:
                this._ODBC__curDatabase.execute(Sql, Params)
            else:
                this._ODBC__curDatabase.execute(Sql)
            if NeedCommit and this._ODBC__conDatabase.autocommit == False:
                this._ODBC__curDatabase.commit()
        except po.Error as poErr:
            print(poErr.args)

    def Close(this):
        """
        ##########################
        [功能描述] 关闭游标和连接.
        [参数列表] 无.
        [返回类型] 无.
        ##########################
        """
        try:
            if not this._ODBC__curDatabase:
                this._ODBC__curDatabase.close()
            if not this._ODBC__conDatabase:
                this._ODBC__conDatabase.close()
        except:
            pass